#ifndef WIN32
#ifndef SOCKET_CAN_H
#define SOCKET_CAN_H

#include <linux/can.h>
#include <linux/can/raw.h>
#include <net/if.h>
#include <map>
#include <thread>
#include <vector>
#include "can_utils.h"

struct RawCAN {
  unsigned int id = 0;
  unsigned char data[64] = {0};
  unsigned short dlc = 8;
  unsigned long timestamp = 0;
  unsigned char channel = 1;
  RawCAN() = default;
  RawCAN(unsigned short _id, unsigned char* _data, unsigned short _dlc,
         unsigned int _timestamp);

  struct ::can_frame can_frame() const;
  struct ::canfd_frame canfd_frame() const;
  std::string ToString() const;
};

class SocketCAN {
 public:
  SocketCAN();
  explicit SocketCAN(const std::string& dev_name,
                     bool absolute_timestamp = false);
  ~SocketCAN();
  bool Init(bool gpio = true);

  bool Update();
  RawCAN can_data{};

  bool Write(const std::vector<RawCAN>& datas);
  bool WriteOne(const RawCAN& data);

  int channel_id() const;

 private:
  std::string can_name_{};
  bool absolute_timestamp_ = false;
  std::string tx2_gpio_{"/dev/calmcargpio"};
  struct iovec iov_ {};
  struct canfd_frame canfd_frame_ {};
  struct msghdr can_msg_hdr_ {};
  sockaddr_can addr_{};
  int socket_{};
  unsigned char channel_id_ = 0;
  // struct ifreq ifr_;
  void SetTransciverOn();
  void SetTransciverOff();
};
#endif
#endif
